Skip to main content

Managing Systemd Services and Units with Systemctl A Guide

· 19 min read
Yashwin Shankar
Front End Developer @ Tech4Biz Solutions Pvt Ltd.
Introduction
Systemd is an important part of many Linux computers. It acts like an organizer that helps your computer work smoothly. Understanding systemd might seem a bit challenging at first, but it's a powerful tool that simplifies managing your computer. Learning about systemd and its tools will give you more control and flexibility over your computer. It's like having a reliable assistant that makes your computer tasks easier. So, let's explore systemd together and see how it can become your computer's helpful companion!

In this guide, we'll explore a command called 'systemctl,' a powerful tool for managing how your computer starts and runs programs. We'll cover how to control programs, check their status, make changes and work with special files that control how everything functions.

Just so you know, not all computers use the same tools. If you come across a message like 'bash: systemctl is not installed,' it means your computer has a different setup. No worries, though – you can still learn a lot from this guide!

Managing Services with Systemctl
The init system is like the manager of your computer. Its main job is to get things ready after you turn on your computer, which we call 'userland' components. It also looks after special helpers called services and daemons while your computer is already up and running. Now, let's jump into some simple ways to take care of these services – it's like learning how to manage different tasks on your computer!

In systemd, everything we want to control is called a 'unit.' Units are like different parts of your computer that systemd knows how to handle. Each unit is put into a group based on what it does, and we describe them using files called unit files. You can tell what type of unit it is by looking at the end of its file name.

When you're managing services, you'll mainly deal with something called 'service units.' These units have files with names ending in .service. But here's something cool: most of the time, you can just leave off the .service part when you're giving commands to systemd. It's clever enough to figure out that you're probably talking about a service!

Getting Services Going and Turning Them Off
To get a systemd service up and running, you use the start command. If you're not the main user of the computer, you'll need to add sudo before the command, because starting a service can change how the computer works:
sudo systemctl start application.service

As we mentioned earlier, when you're dealing with services in systemd, you usually don't need to worry about typing the ".service" part. So, you can just type the command like this:
sudo systemctl start application

While you can use the simplified command we mentioned earlier for most things, for better clarity in our instructions, we'll include the ".service" part in the following commands.

To turn off a service that's currently running, use the stop command instead:
sudo systemctl stop application.service

Refreshing and Rebooting Services
To give a running service a fresh start, you can use the restart command:
sudo systemctl restart application.service

If the program you're using can update its settings without needing to restart, you can use the reload command to make that happen:
sudo systemctl reload application.service

If you're not sure whether the service can update its settings without restarting, you can use the reload-or-restart command. This smart command will try to update the settings in place if possible. If not, it will simply restart the service with the new settings.
sudo systemctl reload-or-restart application.service

Turning Services On and Off
The commands we talked about earlier are handy for turning services on or off while you're using your computer. But if you want a service to start automatically every time you turn on your computer, you need to tell systemd to do that.

To make a service start automatically when you boot up your computer, use the enable command:
sudo systemctl enable application.service

When you use the enable command, it basically creates a special link. This link points from where your computer usually keeps track of services (like in /lib/systemd/system or /etc/systemd/system) to the place where systemd checks for things to start automatically (usually /etc/systemd/system/some_target.target.wants).

Now, if you change your mind and don't want a service to start automatically anymore, you can type:
sudo systemctl disable application.service

This will simply undo the special link that makes the service start automatically.

Remember, when you enable a service, it doesn't start running right away. If you want it to start now and also whenever you turn on your computer, you'll need to use both the start and enable commands.

Checking How Services Are Doing
To see how a service is doing on your computer, you can use the status command:
systemctl status application.service

This will give you information about the service, like whether it's running or not, where it's organized in the system, and some early details from its logs.

For example, if you check the status of an Nginx server, you might see something like this:
Output
● nginx.service - A high performance web server and a reverse proxy server
 Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)
 Active: active (running) since Tue 2015-01-27 19:41:23 EST; 22h ago
Main PID: 495 (nginx)
 CGroup: /system.slice/nginx.service
         ├─495 nginx: master process /usr/bin/nginx -g pid /run/nginx.pid; error_log stderr;
         └─496 nginx: worker process
Jan 27 19:41:23 desktop systemd[1]: Starting A high performance web server and a reverse proxy server...
Jan 27 19:41:23 desktop systemd[1]: Started A high performance web server and a reverse proxy server.

This gives you a helpful summary of how the application is doing, letting you know if there are any issues or if anything needs your attention.

If you want to check if a unit (like a service) is currently doing its job (running), you can use the is-active command:
systemctl is-active application.service

This will tell you whether the unit (like a service) is currently working (active) or not (inactive). If it's active, you'll get a "0" exit code, which is handy for understanding results in shell scripts.

To check if the unit is set to start automatically, you can use the is-enabled command:
systemctl is-enabled application.service

This will show you if the service is set to start automatically or not. It'll also give you a "0" or "1" exit code to help you understand the answer.

Another thing you can check is if the unit (like a service) has run into any issues during startup. This is known as a "failed state," indicating there was a problem getting the unit started:
systemctl is-failed application.service

When you check, it will say "active" if everything's running smoothly, or "failed" if there's been a problem. If the unit was stopped on purpose, it might say "unknown" or "inactive." If you see a "0" exit status, it means something went wrong, while a "1" exit status means something else happened.

Understanding Your System's Situation
The commands we've talked about are great for handling individual services, but they don't give us a good picture of what's happening with the whole system. Luckily, there are some other systemctl commands that help with that.

Checking What's Going On

To check out everything that's currently running on your computer, you can use the list-units command:
systemctl list-units

This will give you a list of everything that systemd is currently managing on your computer. It'll look something like this:
Output
UNIT                                      LOAD   ACTIVE SUB     DESCRIPTION
atd.service                               loaded active running ATD daemon
avahi-daemon.service                      loaded active running Avahi mDNS/DNS-SD Stack
dbus.service                              loaded active running D-Bus System Message Bus
dcron.service                             loaded active running Periodic Command Scheduler
dkms.service                              loaded active exited  Dynamic Kernel Modules System
getty@tty1.service                        loaded active running Getty on tty1
. . .

The information you'll see is organized into columns:
  • UNIT: The name of the thing systemd is managing.
  • LOAD: It tells you if systemd has read the instructions for that thing. If it's "loaded," it means systemd knows what to do with it.
  • ACTIVE: This gives you a quick summary of whether the thing is up and running. It's a simple way to know if it's working as it should
  • SUB: This is a bit more detailed and specific to the type and state of the thing. It provides extra information about how the thing is doing.
  • DESCRIPTION: A short description of what that thing is or what it does.

When you run the list-units command, it usually shows only the units that are currently active. So, in the columns, you'll see "loaded" for whether systemd knows what to do with it, and "active" for whether it's up and running.Actually, when you just type systemctl without adding anything else, it does the same thing – it shows you the active units by default.
systemctl

If you want systemctl to show you more detailed information, you can add extra instructions called flags. For example, if you want to see all the units that systemd knows about, whether they're currently active or not, you can use the --all flag like this:
systemctl list-units --all

This will display all the units that systemd knows about, whether they're active or not. It includes units that systemd tried to load but couldn't find, as well as units that were active but are now inactive.

If you want to narrow down the results, you can use other flags. For instance, you can use --state= to specify whether you want to see information about what's loaded, active, or in a particular state. Don't forget to keep the --all flag so that systemctl shows units even if they're not currently active.
systemctl list-units --all --state=inactive

You can also use another filter called --type= to show only the type of units you're interested in. For instance, if you want to see only active service units, you can use:
systemctl list-units --type=service

Viewing All Unit Files

The list-units command shows only the units that systemd has tried to understand and use. However, this might not include all the units available on your system. To see every single unit file that your system has, even if systemd hasn't looked at them yet, you can use the list-unit-files command instead:
systemctl list-unit-files

Units are like descriptions of things that systemd knows about. When you use list-unit-files, it doesn't show details from all those descriptions, just the names and their current state. The list has two columns: one for the unit file's name and one for its current state.
Output
UNIT FILE                                  STATE
proc-sys-fs-binfmt_misc.automount          static
dev-hugepages.mount                        static
dev-mqueue.mount                           static
proc-fs-nfsd.mount                         static
proc-sys-fs-binfmt_misc.mount              static
sys-fs-fuse-connections.mount              static
sys-kernel-config.mount                    static
sys-kernel-debug.mount                     static
tmp.mount                                  static
var-lib-nfs-rpc_pipefs.mount               static
org.cups.cupsd.path                        enabled
. . .

The state you see will typically be one of these: enabled, disabled, static or masked.
In this case:
  • Enabled: The unit can be turned on.
  • Disabled: The unit is turned off.
  • Static: This means the unit doesn't have the necessary info to be turned on. It might do a one-time thing or is needed only by another unit.
We'll talk about what "masked" means in just a bit.

Controlling Units
Up until now, we've been dealing with services and checking what systemd knows about them. But there's more we can learn about these units using some extra commands. Let's dive into more details!

Viewing Unit Details

To see the detailed instructions that systemd is using for a particular unit, you can use the cat command. This feature was added starting from systemd version 209. For example, to look at the unit file for the atd scheduling daemon, you could type:
systemctl cat atd.service

Output
[Unit]
Description=ATD daemon
[Service]
Type=forking
ExecStart=/usr/bin/atd
[Install]
WantedBy=multi-user.target

The output shows the set of instructions systemd is currently using for that unit. This could be useful if you've made changes to unit files or if you've adjusted specific options in a part of a unit file (we'll talk about this later).

Checking Dependencies

If you want to check all the things a unit depends on, you can use the list-dependencies command:
systemctl list-dependencies sshd.service

This will show you a map of dependencies, which are basically the things that need to be taken care of before the unit you're interested in can start. Dependencies include units that are necessary for or wanted by the units above them in the hierarchy.
Output
sshd.service
├─system.slice
└─basic.target
├─microcode.service
├─rhel-autorelabel-mark.service
├─rhel-autorelabel.service
├─rhel-configure.service
├─rhel-dmesg.service
├─rhel-loadmodules.service
├─paths.target
├─slices.target
. . .

If you want to see all the dependencies, including those that keep going down the line, you can use the --all flag. This is particularly handy when dealing with .target units, which represent different system states.

If you're curious about which units depend on the one you're looking at, you can add the --reverse flag. Additionally, there are two more helpful flags: --before shows units that should start before the specified unit, and --after shows units that should start after the specified unit.

Inspecting Unit Details

If you want to see the detailed properties of a unit, you can use the show command. This will give you a list of settings for that unit, displayed in a key=value format.
systemctl show sshd.service

Output
Id=sshd.service
Names=sshd.service
Requires=basic.target
Wants=system.slice
WantedBy=multi-user.target
Conflicts=shutdown.target
Before=shutdown.target multi-user.target
After=syslog.target network.target auditd.service systemd-journald.socket basic.target system.slice
Description=OpenSSH server daemon
. . .

If you only want to see one specific detail, you can use the -p flag with the property name. For example, to find out about conflicts that the sshd.service unit might have, you can type:
systemctl show sshd.service -p Conflicts

Output
Conflicts=shutdown.target

Blocking and Unblocking Units
In addition to stopping or disabling a service, systemd allows you to prevent a unit from starting altogether, whether it's done automatically or manually. This is known as "masking" the unit, and you can do it using the mask command:
sudo systemctl mask nginx.service

This will make sure that the Nginx service can't start, whether someone tries to start it automatically or manually, as long as it stays masked.

If you look at the list of unit files, you'll now see that the service is marked as "masked":
systemctl list-unit-files

Output
. . .
kmod-static-nodes.service              static
ldconfig.service                       static
mandb.service                          static
messagebus.service                     static
nginx.service                          masked
quotaon.service                        static
rc-local.service                       static
rdisc.service                          disabled
rescue.service                         static
. . .

If you try to start the service, you'll get a message like this:
sudo systemctl start nginx.service

Output
Failed to start nginx.service: Unit nginx.service is masked.

To make a unit available for use again, you can use the unmask command:
sudo systemctl unmask nginx.service

This will bring the unit back to how it was before, so you can start or enable it again.

Adjusting Unit Configuration
While we won't cover the exact layout of unit files in this tutorial, systemctl has features that let you make changes to them if needed. This feature was added starting from systemd version 218.

When you use the edit command, it'll open up the unit file so you can make adjustments
sudo systemctl edit nginx.service

This will be like an empty page where you can add or change instructions for the unit. A new folder will be made in the /etc/systemd/system directory. The folder will have the unit's name with .d added to it. For example, if it's for nginx.service, a folder named nginx.service.d will be created:

Inside this new folder, a little file called override.conf will be made. When systemd loads the unit, it will combine this snippet with the entire unit file in memory. Whatever is written in the snippet will be more important than what's in the original unit file.

If you want to make changes directly to the full unit file instead of creating a snippet, you can add the --full flag:
sudo systemctl edit --full nginx.service

This will open the current unit file in the editor, so you can make changes. Once you're done and exit the editor, the updated file will be saved in /etc/systemd/system. This version will be more important than the system's original unit definition, typically stored in /lib/systemd/system.

If you want to undo any changes you've made, you can either delete the unit's .d configuration folder or the edited service file from /etc/systemd/system. For example, to get rid of a snippet, you could type:
sudo rm -r /etc/systemd/system/nginx.service.d

To delete a fully modified unit file, you can type:
sudo rm /etc/systemd/system/nginx.service

After removing the file or folder, you'll want to reload the systemd process. This ensures that systemd stops using those files and goes back to using the original ones from the system. To do this, just type:
sudo systemctl daemon-reload

Changing the System Mode with Targets
Targets are like special instruction files that describe a particular situation or a point where the system is coordinated to do something. These files, known as targets, can be recognized by their .target ending. Targets don't do much on their own; their main job is to bring together and organize other units.

Think of targets like settings that can put your system into specific modes, kind of like the runlevels in other init systems. They act as a guide for when certain functions are ready, so you can specify the state you want without worrying about all the specific pieces needed to make it happen.

Here's a simple way to understand: Imagine there's a "swap.target" that shows when your system's swap memory is ready to use. Other units, like programs or services, can connect with this target by saying they're "WantedBy=" or "RequiredBy=" the swap.target in their settings. So, if a unit needs the swap to work properly, it can mention this by using "Wants=", "Requires=", or "After=" to show how they're related.

Choosing the Default System Mode

The systemd process starts with a default setting, known as the default target, when you boot up the system. This target sets the stage for bringing the system into the state you want. To see what the default target is for your system, just type:
systemctl get-default

Output
multi-user.target

If you want to choose a different default setting, you can use the set-default command. For example, if you have a graphical desktop installed and you want your system to start up with that by default, you can change the default setting accordingly:
sudo systemctl set-default graphical.target

Viewing System Modes

To see what system modes are available on your system, just type:
systemctl list-unit-files --type=target

Unlike runlevels, where only one can be active, with targets, you can have multiple system modes active at the same time. An active mode means that systemd has tried to start all the connected units and hasn't attempted to stop them yet. To check all the active modes, simply type:
systemctl list-units --type=target

Switching to a Specific System Mode

You can activate all the units linked to a target and deactivate all units not connected to that target. The command for doing this is appropriately called "isolate." It's similar to changing the runlevel in other init systems.

For example, if you're currently using a graphical environment with graphical.target active, you can close the graphical system and switch the system to a multi-user command line state by isolating the multi-user.target. Because graphical.target depends on multi-user.target but not the other way around, all the graphical units will be stopped.

Before you do this, it's a good idea to check the dependencies of the target you want to isolate. This ensures you won't accidentally stop important services.
systemctl list-dependencies multi-user.target

Once you're sure about the units that need to stay active, you can switch to the desired system mode by typing:
sudo systemctl isolate multi-user.target

Quick Commands for Key Events

There are special settings for important events like turning off or restarting the system. Yet, systemctl also offers some shortcuts that make things a bit easier.

For example, instead of typing "isolate rescue.target" to switch the system to rescue (single-user) mode, you can simply use the rescue command:
sudo systemctl rescue

This also includes a useful feature of notifying all logged-in users about the event.

To shut down the system, you can use the halt command:
sudo systemctl halt

To completely turn off the system, simply use the poweroff command:
sudo systemctl poweroff

You can restart the system by using the reboot command:
sudo systemctl reboot

These commands also notify logged-in users about the event, which just isolating or running the target won't do. Most systems are set up to recognize the shorter, more common commands for these actions to work smoothly with systemd.

For example, to restart the system, you can usually just type:
sudo reboot

Conclusion :

Now you have a grasp of the essential functionalities of the systemctl command, which allows you to interact with and oversee your systemd setup. systemctl is your primary tool for managing services and system states.

While systemctl mainly deals with the core systemd process, keep in mind that other parts of the systemd ecosystem are managed by different tools. For example, log management and user sessions are handled by separate daemons and utilities like journald/journalctl and logind/loginctl. Getting familiar with these tools will make system management a smoother task.

Ready to explore more? Learn about other systemd tools and daemons to enhance your system management skills!